home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / comms / other / slrn / slrn_src / src / slrn.c < prev    next >
C/C++ Source or Header  |  1999-05-14  |  35KB  |  1,710 lines

  1. /* -*- mode: C; mode: fold -*- */
  2. /* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
  3.  *
  4.  * This file is part of slrn.
  5.  *
  6.  * Slrn is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation; either version 2, or (at your option) any
  9.  * later version.
  10.  * 
  11.  * Slrn is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * for more details.
  15.  * 
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with Slrn; see the file COPYING.  If not, write to the Free
  18.  * Software Foundation, 59 Temple Place - Suite 330, 
  19.  * Boston, MA  02111-1307, USA.
  20.  */
  21.  
  22. #include "config.h"
  23. #include "slrnfeat.h"
  24. /*{{{ Include files */
  25.  
  26. #include <stdio.h>
  27. #include <signal.h>
  28. #include <string.h>
  29.  
  30.  
  31. #ifdef HAVE_STDLIB_H
  32. # include <stdlib.h>
  33. #endif
  34.  
  35. #ifdef HAVE_UNISTD_H
  36. # include <unistd.h>
  37. #endif
  38.  
  39. #ifdef VMS
  40. # include "vms.h"
  41. #else
  42. # if !defined(sun) && !defined(IBMPC_SYSTEM)
  43. #  include <sys/ioctl.h>
  44. # endif
  45. # ifdef HAVE_TERMIOS_H
  46. #  include <termios.h>
  47. # endif
  48. # ifdef SYSV
  49. #  include <sys/termio.h>
  50. #  include <sys/stream.h>
  51. #  include <sys/ptem.h>
  52. #  include <sys/tty.h>
  53. # endif
  54. # ifndef __os2__
  55. #  include <sys/types.h>
  56. #  include <sys/stat.h>
  57. # endif
  58. #endif /* !VMS */
  59.  
  60. #ifdef HAVE_SYS_WAIT_H
  61. # include <sys/wait.h>
  62. #endif
  63.  
  64. #include <slang.h>
  65. #include "jdmacros.h"
  66.  
  67.  
  68. #include <errno.h>
  69.  
  70. #include "server.h"
  71. #include "slrn.h"
  72. #include "group.h"
  73. #include "misc.h"
  74. #include "startup.h"
  75. #include "art.h"
  76. #include "score.h"
  77. #include "util.h"
  78. #include "chmap.h"
  79.  
  80. #if SLRN_USE_SLTCP
  81. # include "sltcp.h"
  82. #endif
  83.  
  84. #if SLRN_HAS_GROUPLENS
  85. # include "grplens.h"
  86. #endif
  87. #if SLRN_HAS_SLANG
  88. # include "interp.h"
  89. #endif
  90. #ifdef __os2__
  91. # define INCL_VIO
  92. # include <os2.h>
  93. #endif
  94.  
  95. #if defined(__NT__) || defined(__WIN32__)
  96. # include <windows.h>
  97. #endif
  98.  
  99. /*}}}*/
  100.  
  101. /*{{{ Global Variables */
  102.  
  103. int Slrn_TT_Initialized = 0;
  104.  
  105. /* If -1, force mouse.  If 1 the mouse will be used on in XTerm.  If 0, 
  106.  * do not use it.
  107.  */
  108. int Slrn_Use_Mouse;
  109.  
  110. int Slrn_Batch;
  111. int Slrn_Suspension_Ok;
  112.  
  113. char *Slrn_Newsrc_File = NULL;
  114. char *Slrn_Lib_Dir = NULL;
  115. Slrn_Mode_Type *Slrn_Current_Mode;
  116.  
  117. int Slrn_Default_Server_Obj = SLRN_DEFAULT_SERVER_OBJ;
  118. int Slrn_Default_Post_Obj = SLRN_DEFAULT_POST_OBJ;
  119.  
  120. /*}}}*/
  121. /*{{{ Static Variables */
  122.  
  123. static int Can_Suspend;
  124. static volatile int Want_Suspension;
  125. static volatile int Want_Window_Size_Change;
  126. static void perform_suspend (int);
  127. static int Current_Mouse_Mode;
  128.  
  129. /*}}}*/
  130. /*{{{ Static Function Declarations */
  131.  
  132. static int suspend_display_mode (int);
  133. static int resume_display_mode (int, int, int);
  134. static void init_suspend_signals (int);
  135. static void slrn_hangup (int);
  136. static void run_winch_functions (int, int);
  137. /*}}}*/
  138.  
  139. /*{{{ Newsrc Locking Routines */
  140.  
  141. static void test_lock( char *file ) /*{{{*/
  142. {
  143.    int pid;
  144.    FILE *fp;
  145.    
  146.    if ((fp = fopen (file, "r")) != NULL)
  147.      {
  148.     if (1 == fscanf (fp, "%d", &pid) )
  149.       {
  150.          if ((pid > 0)
  151. #if !defined(IBMPC_SYSTEM)
  152.          && (0 == kill (pid, 0))
  153. #endif
  154.          )
  155.            {
  156. #if defined(IBMPC_SYSTEM)
  157.           slrn_exit_error ("\
  158. slrn: pid %d is locking the newsrc file. If you're not running another\n\
  159.       copy of slrn, delete the file %s", 
  160.                    pid, file);
  161. #else
  162.           slrn_exit_error ("slrn: pid %d is locking the newsrc file.", pid);
  163. #endif
  164.            }
  165.       }
  166.     slrn_fclose (fp);
  167.      }
  168. }
  169.  
  170. /*}}}*/
  171.  
  172. static int make_lock( char *file ) /*{{{*/
  173. {
  174.    int pid;
  175.    FILE *fp;
  176.    
  177. #ifdef VMS
  178.    fp = fopen (file, "w", "fop=cif");
  179. #else
  180.    fp = fopen (file, "w");
  181. #endif
  182.    
  183.    if (fp == NULL) return -1;
  184.    
  185.    pid = getpid ();
  186.    if (EOF == fprintf (fp, "%d", pid))
  187.      {
  188.     slrn_fclose (fp);
  189.     return -1;
  190.      }
  191.    return slrn_fclose (fp);
  192. }
  193.  
  194. /*}}}*/
  195.  
  196. static void lock_file (int how) /*{{{*/
  197. {
  198.    char file[SLRN_MAX_PATH_LEN];
  199.    char name[256];
  200.    static int not_ok_to_unlock;
  201. #if SLRN_HAS_RNLOCK
  202.    int rnlock = 0;
  203.    char file_rn[SLRN_MAX_PATH_LEN];
  204. #endif
  205.    
  206.    if (Slrn_Newsrc_File == NULL) return;
  207.    if (not_ok_to_unlock) return;
  208.    
  209.    not_ok_to_unlock = 1;
  210.  
  211. #ifdef SLRN_USE_OS2_FAT
  212.    slrn_os2_make_fat (name, Slrn_Newsrc_File, ".lck");
  213. #else
  214.    sprintf (name, "%s-lock", Slrn_Newsrc_File);
  215. #endif
  216.  
  217.    slrn_make_home_filename (name, file);
  218.    
  219. #if SLRN_HAS_RNLOCK
  220.    if (0 == strcmp(".newsrc", Slrn_Newsrc_File))
  221.      {
  222.     rnlock = 1;
  223.     slrn_make_home_filename (".rnlock", file_rn);
  224.      }
  225. #endif
  226.  
  227.    if (how == 1)
  228.      {
  229.     test_lock (file);
  230. #if SLRN_HAS_RNLOCK
  231.     if (rnlock) test_lock (file_rn);
  232. #endif
  233.     if (-1 == make_lock (file))
  234.       {
  235.          slrn_exit_error ("Unable to create lock file %s.", file);
  236.       }
  237.     
  238. #if SLRN_HAS_RNLOCK
  239.     if (rnlock && (-1 == make_lock (file_rn)))
  240.       {
  241.          slrn_delete_file (file); /* delete the "normal" lock file */
  242.          slrn_exit_error ("Unable to create lock file %s.", file_rn);
  243.       }
  244. #endif       
  245.      }
  246.    else
  247.      {
  248.     if (-1 == slrn_delete_file (file))
  249.       {
  250.          /* slrn_exit_error ("Unable to remove lockfile %s.", file); */
  251.       }
  252. #if SLRN_HAS_RNLOCK
  253.         if (rnlock && -1 == slrn_delete_file (file_rn))
  254.       {
  255.          /* slrn_exit_error ("Unable to remove lockfile %s.", file_rn); */
  256.       }
  257. #endif
  258.      }
  259.    not_ok_to_unlock = 0;
  260. }
  261.  
  262. /*}}}*/
  263.  
  264. /*}}}*/
  265.  
  266. /*{{{ Signal Related Functions */
  267.     
  268. /*{{{ Low-Level signal-related utility functions */
  269.  
  270. static void init_like_signals (int argc, int *argv, /*{{{*/
  271.                    void (*f0)(int), 
  272.                    void (*f1)(int), 
  273.                    int state)
  274. {
  275. #ifdef HAVE_SIGACTION
  276.    struct sigaction sa;
  277. #endif
  278.    int i;
  279.  
  280.    if (state == 0)
  281.      {
  282.     for (i = 0; i < argc; i++)
  283.       SLsignal_intr (argv[i], f0);
  284.     return;
  285.      }
  286.  
  287.    for (i = 0; i < argc; i++)
  288.      {
  289.     int sig = argv[i];
  290.     SLsignal_intr (sig, f1);
  291.  
  292. #if defined(SLRN_POSIX_SIGNALS)
  293.     if (-1 != sigaction (sig, NULL, &sa))
  294.       {
  295.          int j;
  296.          for (j = 0; j < argc; j++)
  297.            {
  298.           if (j != i) sigaddset (&sa.sa_mask, argv[j]);
  299.            }
  300.          
  301.          (void) sigaction (sig, &sa, NULL);
  302.       }
  303. #endif
  304.      }
  305. }
  306.  
  307. /*}}}*/
  308.  
  309.  
  310.  
  311. /*}}}*/
  312.  
  313. /*{{{ Suspension signals */
  314.  
  315. #ifdef REAL_UNIX_SYSTEM
  316. #define SUSPEND_STACK_SIZE 512
  317. static char Suspend_Stack [SUSPEND_STACK_SIZE];
  318. static unsigned int Suspension_Stack_Depth = 0;
  319. static int Ok_To_Suspend = 0;
  320. #endif
  321.  
  322. static int Suspend_Sigtstp_Suspension = 0;
  323.  
  324. void slrn_push_suspension (int ok) /*{{{*/
  325. {
  326. #ifdef REAL_UNIX_SYSTEM
  327.    if (Suspension_Stack_Depth < SUSPEND_STACK_SIZE)
  328.      {
  329.     Suspend_Stack [Suspension_Stack_Depth] = Ok_To_Suspend;
  330.      }
  331.    else ok = 0;
  332.    
  333.    Suspension_Stack_Depth++;
  334.    
  335.    (void) slrn_handle_interrupts ();
  336.  
  337.    Ok_To_Suspend = ok;
  338. #endif
  339. }
  340. /*}}}*/
  341. void slrn_pop_suspension (void) /*{{{*/
  342. {
  343. #ifdef REAL_UNIX_SYSTEM
  344.    
  345.    if (Suspension_Stack_Depth == 0)
  346.      {
  347.     slrn_error ("pop_suspension: underflow!");
  348.     return;
  349.      }
  350.    
  351.    Suspension_Stack_Depth--;
  352.    
  353.    if (Suspension_Stack_Depth < SUSPEND_STACK_SIZE)
  354.      {
  355.     Ok_To_Suspend = Suspend_Stack [Suspension_Stack_Depth];
  356.      }
  357.    else Ok_To_Suspend = 0;
  358.  
  359.    (void) slrn_handle_interrupts ();   
  360. #endif
  361. }
  362. /*}}}*/
  363.  
  364. /* This function is called by the SIGTSTP handler.  Since it operates 
  365.  * in an asynchronous fashion, care must be exercised to control when that
  366.  * can happen.  This is accomplished via the push/pop_suspension functions.
  367.  */
  368. static void sig_suspend (int sig)
  369. {
  370. #ifdef REAL_UNIX_SYSTEM
  371.    sig = errno;
  372.    
  373.    if (Ok_To_Suspend 
  374.        && (0 == Suspend_Sigtstp_Suspension))
  375.      {
  376.     perform_suspend (1);
  377.      }
  378.    else Want_Suspension = 1;
  379.    
  380.    init_suspend_signals (1);
  381.    errno = sig;
  382. #endif
  383. }
  384.  
  385. static void init_suspend_signals (int state) /*{{{*/
  386. {
  387.    int argv[2];
  388.    int argc = 0;
  389.    
  390.    if (Can_Suspend == 0)
  391.      return;
  392.  
  393. #ifdef SIGTSTP
  394.    argv[argc++] = SIGTSTP;
  395. #endif
  396.    
  397. #ifdef SIGTTIN
  398.    argv[argc++] = SIGTTIN;
  399. #endif
  400.  
  401.    init_like_signals (argc, argv, SIG_DFL, sig_suspend, state);
  402. }
  403.  
  404. /*}}}*/
  405.  
  406. static void perform_suspend (int smg_suspend_flag) /*{{{*/
  407. {
  408. #if !defined(SIGSTOP) || !defined(REAL_UNIX_SYSTEM)
  409.    slrn_error ("Not implemented.");
  410.    Want_Suspension = 0;
  411. #else
  412.    
  413.    int init;
  414.    int mouse_mode = Current_Mouse_Mode;
  415.  
  416. # ifdef SLRN_POSIX_SIGNALS
  417.    sigset_t mask;
  418.  
  419.    Want_Suspension = 0;
  420.    if (Can_Suspend =